package com.podium.auth.service.impl;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.podium.auth.entity.LoginUser;
import com.podium.auth.service.TokenService;
import com.podium.auth.utils.Identity;
import com.podium.auth.utils.ServletUtils;
import com.podium.comment.utils.cache.CacheUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.LinkedList;


/**
 * @author 邵文泽
 * @description 密钥服务实现类
 * @date 2025/4/14 17:57
 */
@Service
public class TokenServiceImpl implements TokenService {


    @Value("${token.header}")
    private String header;

    @Value("${token.secret}")
    private String secret;

    @Value("${token.expireTime}")
    private int expireTime;

    @Value("${token.size}")
    private int size;

    public static final String LOGIN_TOKEN_KEY = "login_token_";

    private static final String LOGIN_USER = "login_user_";

    @Autowired
    private CacheUtils cacheUtils;

    /**
     * 创建Token
     *
     * @param loginUser 登录用户信息
     * @return 生成的Token
     */
    @Override
    public String createToken(LoginUser loginUser) {

        String token = Identity.obtainUuId();
        loginUser.setToken(token);

        loginUser.setIpaddr(ServletUtils.getClientIp());
        // 设置登录过期时间
        refreshToken(loginUser);

        return createJwtToken(token);
    }

    /**
     * 获取登录用户
     *
     * @param request HttpServletRequest对象
     * @return 登录用户信息
     */
    @Override
    public LoginUser getLoginUser(HttpServletRequest request) {
        try {
            String token = request.getHeader(header);
            if (StringUtils.hasLength(token) && !"null".equals(token)) {
                token = token.replace("Bearer ", "");
                Claim loginUserKey = JWT.decode(token).getClaim("login_user_key");
                String token1 = loginUserKey.asString();
                return cacheUtils.getCacheObject(LOGIN_TOKEN_KEY + token1,  LoginUser.class);
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除登录用户
     *
     * @param request HttpServletRequest对象
     */
    @Override
    public void delLoginUser(HttpServletRequest request) {
        LoginUser loginUser = getLoginUser(request);
        String token = loginUser.getToken();
        if (StringUtils.hasLength(token)) {
            cacheUtils.removeCache(LOGIN_TOKEN_KEY + token);
        }
    }

    /**
     * 验证Token
     *
     * @param loginUser 登录用户信息
     */
    @Override
    public void verifyToken(LoginUser loginUser) {
        if (cacheUtils.getCacheObject(LOGIN_USER + loginUser.getToken(), LoginUser.class) != null) {
            refreshToken(loginUser);
        }
    }

    /**
     * 刷新Token
     *
     * @param loginUser 登录用户信息
     */
    public void refreshToken(LoginUser loginUser) {
        loginUser.setLoginTime(System.currentTimeMillis());
        loginUser.setExpireTime(loginUser.getLoginTime() + (long) expireTime * 60 * 1000);
        String token = loginUser.getToken();

        // 获取缓存中的 token 队列
        @SuppressWarnings("unchecked")
        LinkedList<String> tokenList = cacheUtils.getCacheObject(LOGIN_USER + loginUser.getUserId(), LinkedList.class);

        // 如果队列不存在，创建新的 LinkedList
        if (tokenList == null) {
            tokenList = new LinkedList<>();
        }

        boolean contains = tokenList.contains(token);
        if (contains) {
            tokenList.remove(token);
        } else if (tokenList.size() >= size) {
            String oldestToken = tokenList.get(0);
            tokenList.remove(oldestToken);
            if (oldestToken != null) {
                cacheUtils.removeCache(LOGIN_TOKEN_KEY + oldestToken);
            }
        }

        // 添加新的 token 到队列尾部
        tokenList.add(token);

        cacheUtils.setCacheObject(LOGIN_USER + loginUser.getUserId(), tokenList, expireTime);
        cacheUtils.setCacheObject(LOGIN_TOKEN_KEY + token, loginUser, expireTime);
    }

    /**
     * 创建JWT Token
     *
     * @param token 令牌
     * @return 生成的JWT Token
     */
    private String createJwtToken(String token) {
        return JWT.create()
                .withClaim("login_user_key", token)
                .withIssuedAt(new Date())
                .withJWTId(Identity.obtainUuId())
                .sign(Algorithm.HMAC512(secret));
    }

}